using DynamicAuthorization.Sdk.Abstarctions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using System.Security.Claims;

namespace DynamicAuthorization.Sdk.Filters;

public class DynamicAuthorizationFilter : IAsyncAuthorizationFilter
{
    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        if (context.Filters.Any(n => n is IAllowAnonymousFilter))
        {
            return;
        }

        if (context.Filters.Any(n => n is DynamicAuthorizationFilter))
        {
            var validator = context.HttpContext.RequestServices.GetRequiredService<IGrantValidator>();

            if (context.ActionDescriptor is ControllerActionDescriptor descriptor)
            {
                var controller = descriptor.ControllerTypeInfo.AsType();
                var action = descriptor.MethodInfo;

                var claim = context.HttpContext.User.Claims.FirstOrDefault(n => n.Type is "name" or ClaimTypes.Name);

                if (claim is null)
                {
                    context.Result = new UnauthorizedResult();

                    return;
                }

                var account = claim.Value;

                var result = await validator.CheckAsync(account, controller, action, context.HttpContext.RequestAborted);

                if (!result)
                {
                    context.Result = new ForbidResult();
                }
            }
        }
    }
}